﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using Ersur.DevTeam;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraReports.UI;
using Extensions;

namespace Ersur
{
    public partial class Products : XForm
    {

        List<int> selectedProducts = new List<int>();

        public Products()
        {
            InitializeComponent();
        }

        void Products_Load(object sender, EventArgs e)
        {
            this.BarcodeRead += Products_BarcodeRead;

            gvProduct.Init(Data.DB.Product);

            gvProduct.OptionsView.NewItemRowPosition = NewItemRowPosition.None;

            gvProduct.AddSummary();
            gvProduct.FormatAsNumber(2,"Price");
            gvProduct.MakeColumnsReadOnly("ProductId", "Select", "Order");
            

            string[] orderedColumns = new string[] {"Select",
                                                    "Order",
                                                    "ProductId",
                                                    "Article",                                                 
                                                    "Count",                                                    
                                                    "Composition",                                                    
                                                    "MinDYELot",
                                                    "Price"
                                                    };

            gvProduct.SetVisibleIndex(orderedColumns);
            gvProduct.SetCaptions("MinDYELot:Minimum DYE Lot Size (kg)", "Price:FOB Istanbul Price ($/kg)");

            GridManager gmProduct = new GridManager(gvProduct);
            gmProduct.GridMenu.AddMenu("Print selected product labels", Print_ProductLabel);

            gmProduct.GridMenu.AddMenu("Select all", SelectAll, true);
            gmProduct.GridMenu.AddMenu("Deselect all", DeselectAll);

            gmProduct.GridMenu.AddMenu("Add to selection", AddToSelection, true);
            gmProduct.GridMenu.AddMenu("Remove from selection", RemoveFromSelection);

            gvProduct.BestFitColumns();

            gvProduct.RowCellClick += gvProduct_RowCellClick;

            gvProduct.CellValueChanged += gvProduct_CellValueChanged;
            gvProduct.CellValueChanging += gvProduct_CellValueChanging;
            gvProduct.ValidateRow += gvProduct_ValidateRow;
            gvProduct.RowUpdated += gvProduct_RowUpdated;

            gvProduct.InvalidRowException += gvProduct_InvalidRowException;
            gvProduct.RowStyle += gvProduct_RowStyle;
        }

        void gvProduct_CellValueChanging(object sender, CellValueChangedEventArgs e)
        { 
            DataRow drCurrent = gvProduct.GetDataRow(e.RowHandle);

            string Article;
            string Count;             
            string Composition;
            string ProductId;
             
            Article = gvProduct.GetRowCellValue(e.RowHandle, "Article").ToStringNN();
            Count = gvProduct.GetRowCellValue(e.RowHandle, "Count").ToStringNN();
            Composition = gvProduct.GetRowCellValue(e.RowHandle, "Composition").ToStringNN();
            ProductId = gvProduct.GetRowCellValue(e.RowHandle, "ProductId").ToStringNN();

            string val = e.Value.ToStringNN();

            if (val != "")
            {
                if (e.Column.FieldName == "Article")
                    Article = val;
                else if (e.Column.FieldName == "Count")
                    Count = val;
                else if (e.Column.FieldName == "Composition")
                    Composition = val;
            }

            List<string> filters = new List<string>();

            if (Article != "")
                filters.Add(string.Format("StartsWith([{0}] , '{1}')", "Article", Article));

            if (Count != "")
                filters.Add(string.Format("StartsWith([{0}] , '{1}')", "Count", Count));

            if (Composition != "")
                filters.Add(string.Format("StartsWith([{0}] , '{1}')", "Composition", Composition));


            gvProduct.ValidateRow -= gvProduct_ValidateRow;
            gvProduct.RowUpdated -= gvProduct_RowUpdated;

            if (ProductId != "")
                gvProduct.ActiveFilterString = "([ProductId] = " + ProductId   + String.Join(" and ", filters.ToArray());
           

            gvProduct.ValidateRow += gvProduct_ValidateRow;
            gvProduct.RowUpdated += gvProduct_RowUpdated;
             
            gvProduct.ShowEditor();
            if (gvProduct.ActiveEditor is TextEdit)
            {
                gvProduct.CellValueChanging -= gvProduct_CellValueChanging;
                TextEdit edit = gvProduct.ActiveEditor as TextEdit;
                edit.Text = val;
                edit.SelectionStart = edit.Text.Length;
                gvProduct.CellValueChanging += gvProduct_CellValueChanging;
            }
        }



        void Products_BarcodeRead(int Barcode)
        { 
            int rowHandle = gvProduct.LocateByValue("ProductId", Barcode);
            gvProduct.FocusedRowHandle = rowHandle;
            foreach (int selectedRowHandle in gvProduct.GetSelectedRows())
                gvProduct.UnselectRow(selectedRowHandle);

            gvProduct.SelectRow(rowHandle);
        }

        void Print_ProductLabel(object sender, EventArgs e)
        {
            gvProduct.EndEditing();

            selectedProducts.Clear();
            foreach (DataRow dr in Data.DB.Product.Select("Order > 0"))
                selectedProducts.Add((int)dr["ProductId"]);

            if (selectedProducts.Count == 0)
            {
                XtraMessageBox.Show("Please select at least 1 article.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            DataSet dsReport = Data.ExecuteDataSet("GetProductReport", string.Join(",", selectedProducts));
            dsReport.Tables[0].Columns.Add("Sira", typeof(int));

            ProductReportSettings settings = new ProductReportSettings();
            settings.ShowDialog();

            int emptyCount = Convert.ToInt32(settings.emptyCount.Value);
            int copyCount = Convert.ToInt32(settings.copyCount.Value);

            if (settings.ManualOrdered)
                foreach (DataRow dr in dsReport.Tables[0].Rows)
                {
                    DataRow[] row = Data.DB.Product.Select("ProductId=" + dr["ProductId"]);
                    if (row.Length > 0)
                        dr["Sira"] = row[0]["Order"];
                }

            ProductReport pr = new ProductReport(dsReport, emptyCount, copyCount);
            pr.ShowPreview();
        }



        void gvProduct_RowCellClick(object sender, RowCellClickEventArgs e)
        {
            if (e.Column.FieldName == "Select" && e.RowHandle > -1)
                ToggleSelection(e.RowHandle);
        }

        void SelectAll(object sender, EventArgs e)
        {
            for (int i = 0; i < gvProduct.DataRowCount; i++)
            {
                bool selected = (bool)gvProduct.GetRowCellValue(i, "Select");
                if (!selected)
                    ToggleSelection(i);
            }
        }

        void DeselectAll(object sender, EventArgs e)
        {
            foreach (DataRow item in Data.DB.Product.Rows)
            {
                item["Select"] = false;
                item["Order"] = DBNull.Value;
            }
        }

        void AddToSelection(object sender, EventArgs e)
        {
            foreach (int rowHandle in gvProduct.GetSelectedRows())
            {
                bool selected = (bool)gvProduct.GetRowCellValue(rowHandle, "Select");
                if (!selected)
                    ToggleSelection(rowHandle);
            }
        }

        void RemoveFromSelection(object sender, EventArgs e)
        {
            foreach (int rowHandle in gvProduct.GetSelectedRows())
            {
                bool selected = (bool)gvProduct.GetRowCellValue(rowHandle, "Select");
                if (selected)
                    ToggleSelection(rowHandle);
            }
        }

        void gvProduct_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
        {
            e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.NoAction;
        }

        void gvProduct_RowStyle(object sender, RowStyleEventArgs e)
        {
            try
            {
                if (e.RowHandle > -1)
                {
                    int currentProductId = (int)gvProduct.GetRowCellValue(e.RowHandle, "ProductId");

                    if (selectedProducts.Contains(currentProductId))
                        e.Appearance.BackColor = Color.PowderBlue;
                    else if ((bool)gvProduct.GetRowCellValue(e.RowHandle, "Select")) //Selected
                        e.Appearance.BackColor = Color.AliceBlue;
                }
            }
            catch (Exception ex)
            {
                AppSession.MainForm.Info = ex.ToString();
            }
        }


        List<int> orderedRows = new List<int>();

        void ToggleSelection(int rowHandle)
        {
            gvProduct.EndEditing();

            DataRow drCurrent = gvProduct.GetDataRow(rowHandle);
            DataRowState rs = drCurrent.RowState;


            bool selected = (bool)drCurrent["Select"];
            gvProduct.SetRowCellValue(rowHandle, "Select", !selected);
            object order = Data.DB.Product.Compute("max(Order)", "");

            if (selected) //ÇIKAR
            {
                int silinenSira = (int)gvProduct.GetRowCellValue(rowHandle, "Order");
                gvProduct.SetRowCellValue(rowHandle, "Order", DBNull.Value);
                foreach (DataRow dr in Data.DB.Product.Select("Order > " + silinenSira.ToString()))
                {
                    dr["Order"] = (int)dr["Order"] - 1;
                }
            }
            else  //EKLE
            {
                if (order == DBNull.Value)
                    order = 1;
                else
                    order = (int)order + 1;

                gvProduct.SetRowCellValue(rowHandle, "Order", order);
            }


            if (rs == DataRowState.Unchanged)
                orderedRows.Add(rowHandle);
        }

        void gvProduct_RowUpdated(object sender, RowObjectEventArgs e)
        {
            if (orderedRows.Contains(e.RowHandle))
                return;

            DataRowView dv = e.Row as DataRowView;
            Data.SaveProduct(dv.Row);
        }

        void gvProduct_CellValueChanged(object sender, CellValueChangedEventArgs e)
        {
            if (orderedRows.Contains(e.RowHandle))
                orderedRows.Remove(e.RowHandle);
        }
         
        void gvProduct_ValidateRow(object sender, ValidateRowEventArgs e)
        { 
            if (orderedRows.Contains(e.RowHandle))
                return;
             

            //TODO: Product da bir değişiklik olunca, bu product ı içeren order ların editDate i now olarak set edilmeli

            int productId = -1;
            int.TryParse(gvProduct.GetRowCellValue(e.RowHandle, "ProductId").ToStringNN(), out productId);
            
            //if (productId > 0)
            {
                string Article;
                string Count;
                string Composition;

                Article = gvProduct.GetRowCellValue(e.RowHandle, "Article").ToStringNN();
                Count = gvProduct.GetRowCellValue(e.RowHandle, "Count").ToStringNN();
                Composition = gvProduct.GetRowCellValue(e.RowHandle, "Composition").ToStringNN();


                string sameFilter = string.Format("ProductId <> {0} and isnull(Article,'') = '{1}' ", productId, Article);
                DataRow[] sameProduct = Data.DB.Product.Select(sameFilter);

                if (sameProduct.Length > 0)
                {
                    XtraMessageBox.Show("Same product exists!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    e.Valid = false;                    
                    return;
                }
                else
                {
                    DialogResult result = XtraMessageBox.Show("Changes will be submitted." + e.RowHandle.ToString() , "Confirmation", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                    e.Valid = (result == DialogResult.OK);
                }
            }
        }

        void txtCount_EditValueChanged(object sender, EventArgs e)
        {
            List<string> filters = new List<string>();

            if (txtArticle.EditValue.ToStringNN() != "")
                filters.Add(string.Format("StartsWith([{0}] , '{1}')", "Article", txtArticle.EditValue));
             
            if (txtCount.EditValue.ToStringNN() != "")
                filters.Add(string.Format("StartsWith([{0}] , '{1}')", "Count", txtCount.EditValue));

            if (txtComposition.EditValue.ToStringNN() != "")
                filters.Add(string.Format("StartsWith([{0}] , '{1}')", "Composition", txtComposition.EditValue));

            gvProduct.ActiveFilterString = String.Join(" and ", filters.ToArray());
        }

        void btnAdd_Click(object sender, EventArgs e)
        {
            decimal count = -1;
            decimal.TryParse(txtCount.Text, out count);

            string sameFilter = string.Format("isnull(Article,'') = '{0}' ", txtArticle.EditValue);
            DataRow[] sameProduct = Data.DB.Product.Select(sameFilter);

            if (sameProduct.Length > 0)
            {
                XtraMessageBox.Show("Same product exists!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            { 
                int minDYLELot= 0;
                int.TryParse(txtMinDYELot.EditValue.ToStringNN(), out minDYLELot);

                decimal price = 0;
                decimal.TryParse(txtPrice.EditValue.ToStringNN(), out count);

                Data.DB.Product.AddProductRow(txtArticle.EditValue.ToStringNN(),
                    count,
                    txtComposition.EditValue.ToStringNN(),
                    minDYLELot,
                    price);

                Data.Save();
            }
        }
    }
}